package com.kmzx.one.project.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kmzx.one.common.utils.MyAssert;
import com.kmzx.one.project.config.data.WXDataConfig;
import com.kmzx.one.project.entity.WxUser;
import com.kmzx.one.project.net.BaseResult;
import com.kmzx.one.project.net.UserResult;
import com.kmzx.one.project.others.dto.FastZoneOutInfo;
import com.kmzx.one.project.others.dto.UserAuthInfo;
import com.kmzx.one.project.others.dto.UserCenterInfo;
import com.kmzx.one.project.others.vos.WXOpenId;
import com.kmzx.one.project.service.ProdService;
import com.kmzx.one.project.service.UserCenterService;
import com.qq.weixin.mp.aes.PKCS7Encoder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import weixin.popular.client.LocalHttpClient;
import weixin.popular.util.EmojiUtil;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;

@Api(tags = "快美甄选_[ 用户_会员_接口 ]")
@RestController
public class UserSelfController extends BaseController {

    protected static Header jsonHeader = new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());

    @Autowired
    private WXDataConfig wxConfig;

    @Autowired
    private UserCenterService userCenterService;


    @Autowired
    private ProdService prodService;

    /**
     * 获取用户的openId
     *
     * @param jsCode
     * @return
     */

    @ApiOperation(value = "1.获取用户的openId(如果已经注册过,则包含userId)", notes = "获取用户的openId(如果已经注册过,则包含userId)")
    @GetMapping(value = "user/getOpenId")
    public UserResult getUserOpenId(@Valid @RequestParam("jsCode") String jsCode) {
        HttpUriRequest httpUriRequest = getHttpUriRequest(jsCode);
        logger.info("当前用户的js_code为:{}", jsCode);
        try {
            WXOpenId result = LocalHttpClient.executeJsonResult(httpUriRequest, WXOpenId.class);
            logger.info("WXOpenId 请求解果为:{}", result);
            String openId = result.openId;
            UserResult userResult = UserResult.Builder.SUCC();
            if (openId != null) {
                userResult.setData(openId);
                WxUser wu = userCenterService.findByOpenId(openId);
                if (wu != null) {
                    userResult.setUserId(wu.getId());
                }
                userResult.setSessionKey(result.getSession_key());
            } else {
                userResult.setErrCode(402);
                userResult.setErrMsg("服务器请求出错,请检查jsCode");
            }
            return userResult;
        } catch (Exception e) {
            return handleUserException(e);
        }
    }

    /**
     * 用户注册
     *
     * @param wxUser 用户参数
     * @param parent 邀请人id
     * @return
     */
    @PostMapping(value = "user/reg")
    @ApiOperation(value = "2.用户注册", notes = "用户注册")
    public BaseResult regOrUpdateUser(WxUser wxUser, String parent) {
        beforeAopRepeat(">>>".concat(wxUser.getOpenId()).concat(wxUser.getNickName()));
        String nickName = wxUser.getNickName();
        String emojis = EmojiUtil.removeAllEmojis(nickName);
        wxUser.setNickName(emojis);

        try {
            WxUser oldUser = userCenterService.findByOpenId(wxUser.getOpenId());
            BaseResult success = BaseResult.Builder.SUCC();
            if (oldUser != null) {
                String oldNickName = oldUser.getNickName();
                String oldAvatar = oldUser.getAvatar();
                if (!oldNickName.equals(emojis) || !oldAvatar.equals(wxUser.getAvatar())) {
                    userCenterService.doUpdateWxUser(wxUser);
                    success.setData(oldUser.getId());
                }
            } else {
                WxUser user = userCenterService.doInsertWxUser(wxUser, parent);
                success.setData(user.getId());
            }
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }


    /**
     * 获取用户手机号
     *
     * @param jsCode
     * @param encryptedData
     * @param iv
     * @return
     */
    @PostMapping(value = "user/getUserPhone")
    @ApiOperation(value = "3.获取用户手机号", notes = "获取用户手机号")
    public BaseResult getUserMobile(String jsCode, String encryptedData, String iv) {
        try {
            MyAssert.notNullObject(jsCode, "jsCode 为null");
            MyAssert.notNullObject(encryptedData, "encryptedData为null");
            MyAssert.notNullObject(iv, "iv值 为null");

            HttpUriRequest uriRequest = getHttpUriRequest(jsCode);
            WXOpenId wxOpenId = LocalHttpClient.executeJsonResult(uriRequest, WXOpenId.class);
            String openId1 = wxOpenId.getOpenId();
            BaseResult success = BaseResult.Builder.SUCC();
            if (openId1 == null) {
                BaseResult fail = BaseResult.Builder.FAIL();
                return fail;
            }
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            Key sKeySpec = new SecretKeySpec(Base64.decodeBase64(wxOpenId.getSession_key()), "AES");
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, new IvParameterSpec(Base64.decodeBase64(iv)));
            byte[] resultByte = cipher.doFinal(Base64.decodeBase64(encryptedData));
            String data = new String(PKCS7Encoder.decode(resultByte), StandardCharsets.UTF_8);

            logger.info("=======data======,{}" + data);

            String openId = wxOpenId.getOpenId();
            logger.info("openId = " + openId);
            WxUser wxUser = userCenterService.findByOpenId(openId);
            String mobile = wxUser.getMobile();
            if (mobile == null || "".equals(mobile)) {
                logger.info("mobile is null ,data,{}" + data);
                JSONObject jsonObject = JSON.parseObject(data);
                String number = jsonObject.getString("phoneNumber");
                wxUser.setMobile(number);
                wxUser.setUpdateTime(new Date());
                userCenterService.doUpdateWxUser(wxUser);
                success.setData(number);
            } else {
                success.setData(mobile);
            }
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }


    public HttpUriRequest getHttpUriRequest(String jsCode) {
        HttpUriRequest httpUriRequest = RequestBuilder.post()
                .setHeader(jsonHeader)
                .setUri(wxConfig.getWxUrl())
                .addParameter("appid", wxConfig.getAppId())
                .addParameter("secret", wxConfig.getAppSecret())
                .addParameter("js_code", jsCode)
                .addParameter("grant_type", "authorization_code")
                .build();
        return httpUriRequest;
    }


    @ApiOperation(value = "4.获取用户的(等级,记录值)信息", notes = "获取用户的(等级,记录值)信息")
    @GetMapping(value = "user/getMainInfo")
    public BaseResult findUserMainInfo(String userId) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            UserCenterInfo info = userCenterService.findUserTopInfo(userId);
            FastZoneOutInfo fastZone = prodService.findFastZone(userId);
            info.setFast(fastZone);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }

    @ApiOperation(value = "5.获取用户的(订单)信息", notes = "获取用户的(订单)信息")
    @GetMapping(value = "user/getExtraInfo")
    public BaseResult findUserExtraInfo(String userId) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            UserCenterInfo info = userCenterService.findUserTwoInfo(userId);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }

    @ApiOperation(value = "6.获取用户的头像", notes = "获取用户的头像")
    @GetMapping(value = "user/downloadIcon")
    public void downloadPics(String pics, HttpServletResponse response) {
        try {
            if (pics == null) {
                BaseResult result = BaseResult.Builder.FAIL().setErrCode(402).setErrMsg("数据为空!");
                response.getWriter().println(result);
            } else if (pics.length() < 8) {
                BaseResult result = BaseResult.Builder.FAIL().setErrCode(402).setErrMsg("数据长度非法!");
                response.getWriter().println(result);
            }
            URL url = new URL(pics);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(3 * 1000);
            response.setContentType("application/force-download");// 设置强制下载不打开            
            response.addHeader("Content-Disposition", "attachment;fileName=" + "a.jpg");
            //得到输入流
            InputStream inputStream = conn.getInputStream();

            OutputStream outputStream = response.getOutputStream();

            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.close();
        } catch (Exception e) {
            BaseResult result = BaseResult.Builder.FAIL().setErrCode(402).setErrMsg("数据为空!");
            try {
                response.getWriter().print(result);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return;
        }
    }

    @ApiOperation(value = "7.检测用户是否有 管家", notes = "检测用户是否有 管家")
    @GetMapping(value = "user/hasFather")
    public BaseResult hasFather(String userId) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            int info = userCenterService.doHasFather(userId);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }


    @ApiOperation(value = "8.进行用户认证")
    @PostMapping(value = "user/auth")
    public BaseResult doUserAuth(String userId, String name, String idCard) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            UserAuthInfo info = userCenterService.doUserAuth(userId, name, idCard);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }


    @ApiOperation(value = "9.检测用户是否 认证")
    @GetMapping(value = "user/hasAuth")
    public BaseResult checkUserAuth(String userId) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            UserAuthInfo info = userCenterService.doCheckUserAuth(userId);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }

    @ApiOperation(value = "10.分享海报")
    @GetMapping(value = "user/share")
    public BaseResult findUserShareMini(String userId) {
        try {
            MyAssert.notNullObject(userId, "userId 为null");
            String info = userCenterService.findUserShareMini(userId);
            BaseResult success = BaseResult.Builder.SUCC().initSuccData(info);
            return success;
        } catch (Exception e) {
            return handleException(e);
        }
    }

}
